//
//  BallLightRender.m
//  BallLight
//
//  Created by Gaomingyang on 2021/4/12.
//  Copyright © 2021 gmy. All rights reserved.
//

#import "BallLightRender.h"
#import "ShaderProgram.h"

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kBallLightVertexShaderString = SHADER_STRING
(
 uniform mat4 vMatrix; //总变换矩阵
 uniform vec3 uLightLocation;//光源位置
 attribute vec3 vPosition;//顶点位置
 varying vec4 vDiffuse;//用于传递给片元着色器的散射光最终强度
 //返回散射光强度
 vec4 pointLight(vec3 normal,vec3 lightLocation,vec4 lightDiffuse){
     //变换后的法向量
     vec3 newTarget = normalize((vMatrix*vec4(normal+vPosition,1)).xyz-(vMatrix*vec4(vPosition,1)).xyz);
     //表面点与光源的方向向量
     vec3 vp = normalize(lightLocation-(vMatrix*vec4(vPosition,1)).xyz);
     return lightDiffuse*max(0.0,dot(newTarget,vp));
 }

 void main(){
     gl_Position = vMatrix * vec4(vPosition,1);//根据总变换矩阵计算次次绘制此顶点位置

     vec4 at = vec4(1.0,1.0,1.0,1.0); //光照强度
     vDiffuse = pointLight(normalize(vPosition),uLightLocation,at);
 }
 );
#else

#endif

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kBallLightFragmentShaderString = SHADER_STRING
(
 precision mediump float;
 varying vec4 vDiffuse;//接受从顶点着色器过来的散射光分量

 void main(){
     vec4 finalColor = vec4(1.0);
     //给此片元着色值
     gl_FragColor = finalColor * vDiffuse + finalColor*vec4(0.15,0.15,0.15,1.0);
 }
 );
#else

#endif
@interface BallLightRender()<GLKViewDelegate>
{
    // Render
    GLuint  _program;
    
    // View
    GLKMatrix4  _projectionMatrix;//投影矩阵
    GLKMatrix4  _viewMatrix;//相机位置
    GLKMatrix4  _MVPMatrix;//计算变换矩阵 4

}
@property (strong, nonatomic) ShaderProgram* shaderProcessor;

@property (strong, nonatomic) EAGLContext* context;
@property (strong, nonatomic) GLKView* glkView;
@property (assign,nonatomic)  int vSize;
@end
struct AttributeHandles
{
    GLint   vPosition;
};

struct UniformHandles
{
    GLuint  uProjectionMatrix;
    GLuint  uMVPMatrix;
    GLuint  uLightLocation;
    
};
@implementation BallLightRender
{
    struct AttributeHandles _attributes;
    struct UniformHandles   _uniforms;
}
- (instancetype)initWithGLKView:(GLKView *)glkView{
    self = [super init];
    if (self) {
        [self commonInitWithGLKView:glkView];
    }
    return self;
}

-(void)commonInitWithGLKView:(GLKView *)glkView{
    [self initOpenglESWithGLKView:glkView];
}
-(void)initOpenglESWithGLKView:(GLKView *)glkView{
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
    // Setup View
    self.glkView = glkView;
    self.glkView.delegate = self;
    self.glkView.context = self.context;
    self.glkView.opaque = YES;
    self.glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    self.glkView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
    
    // Initialize Class Objects
    self.shaderProcessor = [[ShaderProgram alloc] init];
    [self resetupOpenGLES];
}
- (void)resetupOpenGLES
{
    [EAGLContext setCurrentContext:self.context];
    // Enable depth test
    glEnable(GL_DEPTH_TEST);
    CGRect screen = [self.glkView bounds];
    float aspectRatio = fabs(screen.size.width / screen.size.height);
    // Projection Matrix
    _projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0), aspectRatio, 3, 20);
    /**
     float eyeX, float eyeY, float eyeZ,
     float centerX, float centerY, float centerZ,
     float upX, float upY, float upZ
     */
    _viewMatrix = GLKMatrix4MakeLookAt(1, -10, -4, 0, 0, 0, 0, 1, 0);
    _MVPMatrix = GLKMatrix4Multiply(_projectionMatrix, _viewMatrix);
    
    // Create the GLSL program
    _program = [self.shaderProcessor BuildProgram:[kBallLightVertexShaderString cStringUsingEncoding:NSUTF8StringEncoding] with:[kBallLightFragmentShaderString cStringUsingEncoding:NSUTF8StringEncoding]];

    // end create program
    glUseProgram(_program);
    
    // Extract the attribute handles
    _attributes.vPosition = glGetAttribLocation(_program, "vPosition");
    
    // Extract the uniform handles
    _uniforms.uMVPMatrix = glGetUniformLocation(_program, "vMatrix");
    _uniforms.uLightLocation = glGetUniformLocation(_program, "uLightLocation");

}
- (void)setDisplay{
    [self.glkView display];
}
# pragma mark - GLKView Delegate
- (void)update:(id)sender {
    [self.glkView display];
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // Clear Buffers
    glClearColor(0.05, 0.05, 0.05, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // Enable Attributes
    glEnableVertexAttribArray(_attributes.vPosition);
    
    glUniformMatrix4fv(_uniforms.uMVPMatrix, 1, false, _MVPMatrix.m);
    glVertexAttribPointer(_attributes.vPosition, 3, GL_FLOAT, GL_FALSE, 0,[self createBallPos]);
//    int screen_width = [UIScreen mainScreen].bounds.size.width;
//    int screen_height = [UIScreen mainScreen].bounds.size.height;
//    NSLog(@"mgslam screen_width:%d  -- screen_height:%d",screen_width,screen_height);
    // 0,0,0, 是中心点
    // 207，448， 是右上角
    // -207,-448 左下角
    
    glUniform3f(_uniforms.uLightLocation, self.lightPositionX, self.lightPositionY, self.lightPositionZ);
    glDrawArrays(GL_TRIANGLE_FAN, 0, ((GLsizei)self.vSize));
    
    // Disable Attributes
    glDisableVertexAttribArray(_attributes.vPosition);
    
}

# pragma mark - GLKViewController Delegate

- (void)glkViewControllerUpdate:(GLKViewController *)controller
{
}


-(float *)createBallPos{
    static  float step = 5.0f;
    //球以(0,0,0)为中心，以R为半径，则球上任意一点的坐标为
    // ( R * cos(a) * sin(b),y0 = R * sin(a),R * cos(a) * cos(b))
    // 其中，a为圆心到点的线段与xz平面的夹角，b为圆心到点的线段在xz平面的投影与z轴的夹角
    NSMutableArray<NSNumber *> *data = [NSMutableArray new];
    float r1,r2;
    float h1,h2;
    float sin,cos;
    for(float i= -90;i<90+step;i+=step){
        r1 = (float)cos(i*M_PI/180.0);
        r2 = (float)cos((i+step)*M_PI/180.0);
        h1 = (float)sin(i*M_PI/180.0);
        h2 = (float)sin((i+step)*M_PI/180.0);
        //固定纬度，360 度旋转遍历一条纬线
        float step2 = step*2;
        for(float j = 0.0f;j<360.0f+step;j+=step2){
        cos = (float)cos(j*M_PI/180.0);
        sin = -(float)sin(j*M_PI/180.0);

            [data addObject:[NSNumber numberWithFloat:(r2*cos)]];
            [data addObject:[NSNumber numberWithFloat:h2]];
            [data addObject:[NSNumber numberWithFloat:(r2*sin)]];
            [data addObject:[NSNumber numberWithFloat:(r1*cos)]];
            [data addObject:[NSNumber numberWithFloat:h1]];
            [data addObject:[NSNumber numberWithFloat:(r1*sin)]];
        
        }
     }
    float * result = malloc(sizeof(float)*(data.count));
            for(int i=0;i<data.count;i++){
                NSNumber *tmpF = data[i];
                result[i] = tmpF.floatValue;
            }
    self.vSize = (int)data.count/3;
    return result;
}
@end
